#include "IfStatement.h"
#include "../Exceptions.h"
#include "../GeneralVisitor.h"

IfStatement::IfStatement(TreeNode* iCondition, TreeNode* iThenPart, TreeNode* iElsePart)
{
    fCondition = iCondition;
    fThenPart = iThenPart;
    fElsePart = iElsePart;
}

IfStatement::~IfStatement()
{
    delete fCondition;
    delete fThenPart;

    if(fElsePart != 0)
        delete fElsePart;
}

void IfStatement::CheckVariables(set<string>& oVariables, string iParentName)
{
    this->fCondition->CheckVariables(oVariables, iParentName);
    this->fThenPart->CheckVariables(oVariables, iParentName);

    if(this->fElsePart != 0)
        this->fElsePart->CheckVariables(oVariables, iParentName);
}

void IfStatement::CheckFunctionCalls(set<FunctionDefinition*>& iAllFunctions, string iParentName)
{
    this->fCondition->CheckFunctionCalls(iAllFunctions, iParentName);
    this->fThenPart->CheckFunctionCalls(iAllFunctions, iParentName);

    if(this->fElsePart != 0)
        this->fElsePart->CheckFunctionCalls(iAllFunctions, iParentName);
}

void IfStatement::CheckClassConstructions(set<ClassDefinition*>& iAllClasses, string iParentName)
{
    this->fCondition->CheckClassConstructions(iAllClasses, iParentName);
    this->fThenPart->CheckClassConstructions(iAllClasses, iParentName);

    if(this->fElsePart != 0)
        this->fElsePart->CheckClassConstructions(iAllClasses, iParentName);
}

void IfStatement::CheckExpressionTypes(map<string, ExpressionType*>& iVarTypes, string iParentName)
{
    this->fCondition->CheckExpressionTypes(iVarTypes, iParentName);
    this->fThenPart->CheckExpressionTypes(iVarTypes, iParentName);

    if(this->fElsePart != 0)
        this->fElsePart->CheckExpressionTypes(iVarTypes, iParentName);

    ExpressionType* lConditionType = this->fCondition->GetType(iVarTypes, iParentName);
    ValueType lType = lConditionType->fType;

    if(!lConditionType->fResolveTypeAtRuntime && lType != Boolean)
    {
        delete lConditionType;
        throw InvalidTypeException(iParentName, "podminka prikazu if", Boolean, lType);
    }

    delete lConditionType;
}

void IfStatement::Accept(GeneralVisitor* iVisitor)
{
    iVisitor->Visit(this);
}

ReturnStatement* IfStatement::GetFirstReturnStatement()
{
    ReturnStatement* lRetFromThen = fThenPart->GetFirstReturnStatement();

    if(lRetFromThen != 0)
        return lRetFromThen;

    if(fElsePart != 0)
        return fElsePart->GetFirstReturnStatement();

    return 0;
}
